home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- * *
- * Copyright (C) 1992 Igor Mandrichenko. *
- * Permission is granted to any individual or institution to use, copy, *
- * or redistribute this software so long as all of the original files *
- * are included unmodified, that it is not sold for profit, and that *
- * this copyright notice is retained. *
- * *
- *************************************************************************/
-
- /*
- * vms.c by Igor Mandrichenko
- * version 1.2-1
- *
- * This module contains routines to extract VMS file attributes
- * from extra field and create file with these attributes. This
- * source is mainly based on sources of file_io.c from UNZIP 4.1
- * by Info-ZIP. [Info-ZIP note: very little of this code is from
- * file_io.c; it has virtually been written from the ground up.
- * Of the few lines which are from the older code, most are mine
- * (G. Roelofs) and I make no claims upon them. On the contrary,
- * my/our thanks to Igor for his contributions!]
- */
-
- /*
- * Revision history:
- * 1.0-1 Mandrichenko 16-feb-1992
- * Recognize -c option
- * 1.0-2 Mandrichenko 17-feb-1992
- * Do not use ASYnchroneous mode.
- * 1.0-3 Mandrichenko 2-mar-1992
- * Make code more standard
- * Use lrec instead of crec -- unzip4.2p does not provide
- * crec now.
- * 1.1 Mandrichenko 5-mar-1992
- * Make use of asynchronous output.
- * Be ready to extract RMS blocks of invalid size (because diff
- * VMS version used to compress).
- * 1.1-1 Mandrichenko 11-mar-1992
- * Use internal file attributes saved in pInfo to decide
- * if the file is text. [GRR: temporarily disabled, since
- * no way to override and force binary extraction]
- * 1.1-2 Mandrichenko 13-mar-1992
- * Do not restore owner/protection info if -X not specified.
- * 1.1-3 Mandrichenko 30-may-1992
- * Set revision date/time to creation date/time if none specified
- * Take quiet flag into account.
- * 1.1-4 Cave Newt 14-jun-1992
- * Check zipfile for variable-length format (unzip and zipinfo).
- * 1.2 Mandrichenko 21-jun-1992
- * Use deflation/inflation for compression of extra blocks
- * Free all allocated space
- * 1.2-1 Mandrichenko 23-jun-1992
- * Interactively select an action when file exists
- */
-
- #ifdef VMS /* VMS only ! */
-
- #ifndef SYI$_VERSION
- #define SYI$_VERSION 4096 /* VMS 5.4 definition */
- #endif
-
- #ifndef VAXC
- /* This definition may be missed */
- struct XAB {
- unsigned char xab$b_cod;
- unsigned char xab$b_bln;
- short int xabdef$$_fill_1;
- char *xab$l_nxt;
- };
-
- #endif
-
- #include "unzip.h"
- #include <ctype.h>
- #include <descrip.h>
- #include <syidef.h>
-
- #define ERR(s) !((s) & 1)
-
- #define BUFS512 8192*2 /* Must be a multiple of 512 */
-
- /*
- * Local static storage
- */
- static struct FAB fileblk;
- static struct XABDAT dattim;
- static struct XABRDT rdt;
- static struct RAB rab;
-
- static struct FAB *outfab = 0;
- static struct RAB *outrab = 0;
- static struct XABFHC *xabfhc = 0;
- static struct XABDAT *xabdat = 0;
- static struct XABRDT *xabrdt = 0;
- static struct XABPRO *xabpro = 0;
- static struct XABKEY *xabkey = 0;
- static struct XABALL *xaball = 0;
- struct XAB *first_xab = 0L, *last_xab = 0L;
-
- static char query = 0;
- static int text_file = 0;
-
- static char locbuf[BUFS512];
- static int loccnt = 0;
- static char *locptr;
-
- static int WriteBuffer();
- static int _flush_blocks();
- static int _flush_records();
- static byte *extract_block();
- static void message();
- static int get_vms_version();
- static void free_up();
- static int replace();
-
- struct bufdsc
- {
- struct bufdsc *next;
- byte *buf;
- int bufcnt;
- };
-
- static struct bufdsc b1, b2, *curbuf;
- static byte buf1[BUFS512], buf2[BUFS512];
-
-
- int check_format() /* return non-0 if format is variable-length */
- {
- int rtype;
- struct FAB fab;
-
- fab = cc$rms_fab;
- fab.fab$l_fna = zipfn;
- fab.fab$b_fns = strlen(zipfn);
- sys$open(&fab);
- rtype = fab.fab$b_rfm;
- sys$close(&fab);
-
- if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)
- {
- fprintf(stderr,
- "\n Error: zipfile is in variable-length record format. Please\n\
- run \"bilf l %s\" to convert the zipfile to stream-LF\n\
- record format. (Bilf.exe, bilf.c and make_bilf.com are included\n\
- in the VMS UnZip source distribution.)\n\n", zipfn);
- return 2; /* 2: error in zipfile */
- }
-
- return 0;
- }
-
-
- #ifndef ZIPINFO
-
- int create_output_file()
- { /* return non-0 if sys$create failed */
- int ierr, yr, mo, dy, hh, mm, ss;
- char timbuf[24]; /* length = first entry in "stupid" + 1 */
- int attr_given = 0; /* =1 if VMS attributes are present in
- * extra_field */
-
- rab = cc$rms_rab; /* fill FAB & RAB with default values */
- fileblk = cc$rms_fab;
-
- text_file =/* pInfo->text || */aflag || cflag;
-
- if (attr_given = find_vms_attrs())
- {
- text_file = 0;
- if (cflag)
- {
- printf("Cannot put VMS file %s to stdout.\n",
- filename);
- free_up();
- return 50;
- }
- }
-
- if (!attr_given)
- {
- outfab = &fileblk;
- outfab->fab$l_xab = 0L;
- if (text_file)
- {
- outfab->fab$b_rfm = FAB$C_VAR; /* variable length records */
- outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
- }
- else
- {
- outfab->fab$b_rfm = FAB$C_STMLF; /* stream-LF record format */
- outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
- }
- }
-
- if (!cflag)
- outfab->fab$l_fna = filename;
- else
- outfab->fab$l_fna = "sys$output:";
-
- outfab->fab$b_fns = strlen(outfab->fab$l_fna);
-
- if ((!attr_given) || xabdat == 0 || xabrdt == 0) /* Use date/time info
- * from zipfile if
- * no attributes given
- */
- {
- static char *month[] =
- {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
- "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
-
- /* fixed-length string descriptor: */
- struct dsc$descriptor stupid =
- {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
-
- yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
- mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
- dy = (lrec.last_mod_file_date & 0x1f);
- hh = (lrec.last_mod_file_time >> 11) & 0x1f;
- mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- ss = (lrec.last_mod_file_time & 0x1f) * 2;
-
- dattim = cc$rms_xabdat; /* fill XABs with default values */
- rdt = cc$rms_xabrdt;
- sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
- hh, mm, ss);
- sys$bintim(&stupid, &dattim.xab$q_cdt);
- memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
-
- if ((!attr_given) || xabdat == 0L)
- {
- dattim.xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = &dattim;
- }
- }
-
- outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */
-
- ierr = sys$create(outfab);
- if (ierr == RMS$_FEX)
- ierr = replace();
-
- if (ierr == 0) /* Canceled */
- return free_up(), 1;
-
- if (ERR(ierr))
- {
- char buf[256];
-
- sprintf(buf, "[ Cannot create output file %s ]\n", filename);
- message(buf, ierr);
- message("", outfab->fab$l_stv);
- free_up();
- return (1);
- }
-
- if (!text_file && !cflag) /* Do not reopen text files and stdout
- * Just open them in right mode */
- {
- /*
- * Reopen file for Block I/O with no XABs.
- */
- if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
- {
- #ifdef DEBUG
- message("[ create_output_file: sys$close failed ]\n", ierr);
- message("", outfab->fab$l_stv);
- #endif
- fprintf(stderr, "Can't create output file: %s\n", filename);
- free_up();
- return (1);
- }
-
-
- outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
- * output */
- outfab->fab$l_xab = 0L; /* Unlink all XABs */
-
- if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
- {
- char buf[256];
-
- sprintf(buf, "[ Cannot open output file %s ]\n", filename);
- message(buf, ierr);
- message("", outfab->fab$l_stv);
- free_up();
- return (1);
- }
- }
-
- outrab = &rab;
- rab.rab$l_fab = outfab;
- if (!text_file) rab.rab$l_rop |= RAB$M_BIO;
- if (!text_file) rab.rab$l_rop |= RAB$M_ASY;
- rab.rab$b_rac = RAB$C_SEQ;
-
- if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
- {
- #ifdef DEBUG
- message("create_output_file: sys$connect failed.\n", ierr);
- message("", outfab->fab$l_stv);
- #endif
- fprintf(stderr, "Can't create output file: %s\n", filename);
- free_up();
- return (1);
- }
-
- locptr = &locbuf[0];
- loccnt = 0;
-
- b1.buf = &buf1[0];
- b1.bufcnt = 0;
- b1.next = &b2;
- b2.buf = &buf2[0];
- b2.bufcnt = 0;
- b2.next = &b1;
- curbuf = &b1;
-
- return (0);
- }
-
- static int replace()
- { /*
- * File exists. Inquire user about futher action.
- */
- char answ[10];
- struct NAM nam;
- int ierr;
-
- if (query == 0)
- {
- do
- {
- fprintf(stderr,
- "Replace %s : [o]verwrite, new [v]ersion or [c]ancel (O,V,C - all) ? ",
- filename);
- fflush(stderr);
- } while (fgets(answ, 9, stderr) == NULL && !isalpha(answ[0])
- && tolower(answ[0]) != 'o'
- && tolower(answ[0]) != 'v'
- && tolower(answ[0]) != 'c');
-
- if (isupper(answ[0]))
- query = answ[0] = tolower(answ[0]);
- }
- else
- answ[0] = query;
-
- switch (answ[0])
- {
- case 'c':
- ierr = 0;
- break;
- case 'v':
- nam = cc$rms_nam;
- nam.nam$l_rsa = filename;
- nam.nam$b_rss = FILNAMSIZ - 1;
-
- outfab->fab$l_fop |= FAB$M_MXV;
- outfab->fab$l_nam = &nam;
-
- ierr = sys$create(outfab);
- if (!ERR(ierr))
- {
- outfab->fab$l_nam = 0L;
- filename[outfab->fab$b_fns = nam.nam$b_rsl] = 0;
- }
- break;
- case 'o':
- outfab->fab$l_fop |= FAB$M_SUP;
- ierr = sys$create(outfab);
- break;
- }
- return ierr;
- }
-
- /*
- * Extra record format
- * ===================
- * signature (2 bytes) = 'I','M'
- * size (2 bytes)
- * block signature (4 bytes)
- * flags (2 bytes)
- * uncomprssed size(2 bytes)
- * reserved (4 bytes)
- * data ((size-12) bytes)
- * ....
- */
-
- #define BC_MASK 07 /* 3 bits for compression type */
- #define BC_STORED 0 /* Stored */
- #define BC_00 1 /* 0byte -> 0bit compression */
- #define BC_DEFL 2 /* Deflated */
-
- struct extra_block
- {
- UWORD sig; /* Extra field block header structure */
- UWORD size;
- ULONG bid;
- UWORD flags;
- UWORD length;
- ULONG reserved;
- byte body[1];
- };
-
- /*
- * Extra field signature and block signatures
- */
-
- #define SIGNATURE "IM"
- #define FABL (cc$rms_fab.fab$b_bln)
- #define RABL (cc$rms_rab.rab$b_bln)
- #define XALLL (cc$rms_xaball.xab$b_bln)
- #define XDATL (cc$rms_xabdat.xab$b_bln)
- #define XFHCL (cc$rms_xabfhc.xab$b_bln)
- #define XKEYL (cc$rms_xabkey.xab$b_bln)
- #define XPROL (cc$rms_xabpro.xab$b_bln)
- #define XRDTL (cc$rms_xabrdt.xab$b_bln)
- #define XSUML (cc$rms_xabsum.xab$b_bln)
- #define EXTBSL 4 /* Block signature length */
- #define RESL 8 /* Rserved 8 bytes */
- #define EXTHL (4+EXTBSL)
- #define FABSIG "VFAB"
- #define XALLSIG "VALL"
- #define XFHCSIG "VFHC"
- #define XDATSIG "VDAT"
- #define XRDTSIG "VRDT"
- #define XPROSIG "VPRO"
- #define XKEYSIG "VKEY"
- #define XNAMSIG "VNAM"
- #define VERSIG "VMSV"
-
-
-
- #define W(p) (*(unsigned short*)(p))
- #define L(p) (*(unsigned long*)(p))
- #define EQL_L(a,b) ( L(a) == L(b) )
- #define EQL_W(a,b) ( W(a) == W(b) )
-
- /****************************************************************
- * Function find_vms_attrs scans ZIP entry extra field if any *
- * and looks for VMS attribute records. Returns 0 if either no *
- * attributes found or no fab given. *
- ****************************************************************/
- int find_vms_attrs()
- {
- byte *scan = extra_field;
- struct extra_block *blk;
- int len;
-
- outfab = xabfhc = xabdat = xabrdt = xabpro = first_xab = last_xab = 0L;
-
- if (scan == NULL)
- return 0;
- len = lrec.extra_field_length;
-
- #define LINK(p) { /* Link xaballs and xabkeys into chain */ \
- if( first_xab == 0L ) \
- first_xab = p; \
- if( last_xab != 0L ) \
- last_xab -> xab$l_nxt = p; \
- last_xab = p; \
- p -> xab$l_nxt = 0; \
- }
- /* End of macro LINK */
-
- while (len > 0)
- {
- blk = (struct block *) scan;
- if (EQL_W(&blk->sig, SIGNATURE))
- {
- byte *block_id;
-
- block_id = &blk->bid;
- if (EQL_L(block_id, FABSIG))
- {
- outfab = (struct FAB *) extract_block(blk, 0,
- &cc$rms_fab, FABL);
- }
- else if (EQL_L(block_id, XALLSIG))
- {
- xaball = (struct XABALL *) extract_block(blk, 0,
- &cc$rms_xaball, XALLL);
- LINK(xaball);
- }
- else if (EQL_L(block_id, XKEYSIG))
- {
- xabkey = (struct XABKEY *) extract_block(blk, 0,
- &cc$rms_xabkey, XKEYL);
- LINK(xabkey);
- }
- else if (EQL_L(block_id, XFHCSIG))
- {
- xabfhc = (struct XABFHC *) extract_block(blk, 0,
- &cc$rms_xabfhc, XFHCL);
- }
- else if (EQL_L(block_id, XDATSIG))
- {
- xabdat = (struct XABDAT *) extract_block(blk, 0,
- &cc$rms_xabdat, XDATL);
- }
- else if (EQL_L(block_id, XRDTSIG))
- {
- xabrdt = (struct XABRDT *) extract_block(blk, 0,
- &cc$rms_xabrdt, XRDTL);
- }
- else if (EQL_L(block_id, XPROSIG))
- {
- xabpro = (struct XABPRO *) extract_block(blk, 0,
- &cc$rms_xabpro, XPROL);
- }
- else if (EQL_L(block_id, VERSIG))
- {
- char verbuf[80];
- int verlen = 0;
- byte *vers;
- char *m;
-
- get_vms_version(verbuf, 80);
- vers = extract_block(blk, &verlen, 0, 0);
- if ((m = strrchr(vers, '-')) != NULL)
- *m = 0; /* Cut out release number */
- if (strcmp(verbuf, vers) && quietflg == 0)
- {
- printf("[ Warning: VMS version mismatch.");
-
- printf(" This version %s --", verbuf);
- strncpy(verbuf, vers, verlen);
- verbuf[verlen] = 0;
- printf(" version made by %s ]\n", verbuf);
- }
- free(vers);
- }
- else if (quietflg == 0)
- fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
- block_id);
- }
- len -= blk->size + 4;
- scan += blk->size + 4;
- }
-
-
- if (outfab != 0)
- { /* Do not link XABPRO,XABRDT now. Leave them for sys$close() */
-
- outfab->fab$l_xab = 0L;
- if (xabfhc != 0L)
- {
- xabfhc->xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = xabfhc;
- }
- if (xabdat != 0L)
- {
- xabdat->xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = xabdat;
- }
- if (first_xab != 0L) /* Link xaball,xabkey subchain */
- {
- last_xab->xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = first_xab;
- }
- return 1;
- }
- else
- return 0;
- }
-
- static void free_up()
- { /*
- * Free up all allocated xabs
- */
- if (xabdat != 0L) free(xabdat);
- if (xabpro != 0L) free(xabpro);
- if (xabrdt != 0L) free(xabrdt);
- if (xabfhc != 0L) free(xabfhc);
- while (first_xab != 0L)
- {
- struct XAB *x;
-
- x = first_xab->xab$l_nxt;
- free(first_xab);
- first_xab = x;
- }
- if (outfab != 0L && outfab != &fileblk)
- free(outfab);
- }
-
- static int get_vms_version(verbuf, len)
- char *verbuf;
- int len;
- {
- int i = SYI$_VERSION;
- int verlen = 0;
- struct dsc$descriptor version;
- char *m;
-
- version.dsc$a_pointer = verbuf;
- version.dsc$w_length = len - 1;
- version.dsc$b_dtype = DSC$K_DTYPE_B;
- version.dsc$b_class = DSC$K_CLASS_S;
-
- if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
- return 0;
-
- /* Cut out trailing spaces "V5.4-3 " -> "V5.4-3" */
- for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
- --m;
- *m = 0;
-
- /* Cut out release number "V5.4-3" -> "V5.4" */
- if ((m = strrchr(verbuf, '-')) != NULL)
- *m = 0;
- return strlen(verbuf) + 1; /* Transmit ending 0 too */
- }
-
- /******************************
- * Function extract_block *
- ******************************/
- /*
- * Extracts block from p. If resulting length is less then needed, fill
- * extra space with corresponding bytes from 'init'.
- * Currently understands 3 formats of block compression:
- * - Simple storing
- * - Compression of zero bytes to zero bits
- * - Deflation. See memextract() from extract.c
- */
- static byte *extract_block(p, retlen, init, needlen)
- struct extra_block *p;
- int *retlen;
- byte *init;
- int needlen;
- {
- byte *block; /* Pointer to block allocated */
- int cmptype;
- int usiz, csiz, max;
-
- cmptype = p->flags & BC_MASK;
- csiz = p->size - EXTBSL - RESL;
- usiz = (cmptype == BC_STORED ? csiz : p->length);
-
- if (needlen == 0)
- needlen = usiz;
-
- if (retlen)
- *retlen = usiz;
-
- #ifndef MAX
- #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
- #endif
-
- if ((block = (byte *) malloc(MAX(needlen, usiz))) == NULL)
- return NULL;
-
- if (init && (usiz < needlen))
- memcpy(block, init, needlen);
-
- switch (cmptype)
- {
- case BC_STORED: /* The simplest case */
- memcpy(block, &(p->body[0]), usiz);
- break;
- case BC_00:
- decompress_bits(block, usiz, &(p->body[0]));
- break;
- case BC_DEFL:
- memextract(block, usiz, &(p->body[0]), csiz);
- break;
- default:
- free(block);
- block = NULL;
- }
- return block;
- }
-
- /*
- * Simple uncompression routine. The compression uses bit stream.
- * Compression scheme:
- *
- * if(byte!=0)
- * putbit(1),putbyte(byte)
- * else
- * putbit(0)
- */
- static void decompress_bits(outptr, needlen, bitptr)
- byte *bitptr;
-
- /* Pointer into compressed data */
- byte *outptr; /* Pointer into output block */
- int needlen; /* Size of uncompressed block */
- {
- ULONG bitbuf = 0;
- int bitcnt = 0;
-
- #define _FILL if(bitcnt+8 <= 32) \
- { bitbuf |= (*bitptr++) << bitcnt;\
- bitcnt += 8; \
- }
-
- while (needlen--)
- {
- if (bitcnt <= 0)
- _FILL;
-
- if (bitbuf & 1)
- {
- bitbuf >>= 1;
- if ((bitcnt -= 1) < 8)
- _FILL;
- *outptr++ = (byte) bitbuf;
- bitcnt -= 8;
- bitbuf >>= 8;
- }
- else
- {
- *outptr++ = 0;
- bitcnt -= 1;
- bitbuf >>= 1;
- }
- }
- }
-
- /***************************/
- /* Function FlushOutput() */
- /***************************/
-
- int FlushOutput()
- {
- if (mem_mode)
- { /* Hope, mem_mode stays constant during
- * extraction */
- int rc = FlushMemory(); /* For mem_extract() */
-
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
- return rc;
- }
-
- /* return PK-type error code */
- /* flush contents of output buffer */
- if (tflag)
- { /* Do not output. Update CRC only */
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
- return 0;
- }
- else
- return text_file ? _flush_records(0) : _flush_blocks(0);
- }
-
- static int _flush_blocks(final_flag) /* Asynchronous version */
- int final_flag;
-
- /* 1 if this is the final flushout */
- {
- int round;
- int rest;
- int off = 0;
- int out_count = outcnt;
- int status;
-
- while (out_count > 0)
- {
- if (curbuf->bufcnt < BUFS512)
- {
- int ncpy;
-
- ncpy = out_count > (BUFS512 - curbuf->bufcnt) ?
- BUFS512 - curbuf->bufcnt :
- out_count;
- memcpy(curbuf->buf + curbuf->bufcnt, outbuf + off, ncpy);
- out_count -= ncpy;
- curbuf->bufcnt += ncpy;
- off += ncpy;
- }
- if (curbuf->bufcnt == BUFS512)
- {
- status = WriteBuffer(curbuf->buf, curbuf->bufcnt);
- if (status)
- return status;
- curbuf = curbuf->next;
- curbuf->bufcnt = 0;
- }
- }
-
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
-
- return (final_flag && (curbuf->bufcnt > 0)) ?
- WriteBuffer(curbuf->buf, curbuf->bufcnt) :
- 0;
- /* 0: no error */
- }
-
- #define RECORD_END(c) ((c) == CR || (c) == LF || (c) == CTRLZ)
-
- static int _flush_records(final_flag)
- int final_flag;
-
- /* 1 if this is the final flushout */
- {
- int rest;
- int end = 0, start = 0;
- int off = 0;
-
- if (outcnt == 0 && loccnt == 0)
- return 0; /* Nothing to do ... */
-
- if (loccnt)
- {
- for (end = 0; end < outcnt && !RECORD_END(outbuf[end]);)
- ++end;
-
- if (end >= outcnt && !final_flag)
- {
- if (WriteRecord(locbuf, loccnt))
- return (50);
- fprintf(stderr, "[ Warning: Record too long (%d) ]\n",
- outcnt + loccnt);
- memcpy(locbuf, outbuf, outcnt);
- locptr = &locbuf[loccnt = outcnt];
- }
- else
- {
- memcpy(locptr, outbuf, end);
- if (WriteRecord(locbuf, loccnt + end))
- return (50);
- loccnt = 0;
- locptr = &locbuf;
- }
- start = end + 1;
-
- if (start < outcnt && outbuf[end] == CR && outbuf[start] == LF)
- ++start;
- }
-
- do
- {
- while (start < outcnt && outbuf[start] == CR) /* Skip CR's at the
- * beginning of rec. */
- ++start;
- /* Find record end */
- for (end = start; end < outcnt && !RECORD_END(outbuf[end]);)
- ++end;
-
- if (end < outcnt)
- { /* Record end found, write the record */
- if (WriteRecord(outbuf + start, end - start))
- return (50);
- /* Shift to the begining of the next record */
- start = end + 1;
- }
-
- if (start < outcnt && outbuf[end] == CR && outbuf[start] == LF)
- ++start;
-
- } while (start < outcnt && end < outcnt);
-
- rest = outcnt - start;
-
- if (rest > 0)
- if (final_flag)
- {
- /* This is a final flush. Put out all remaining in
- * the buffer */
- if (loccnt && WriteRecord(locbuf, loccnt))
- return (50);
- }
- else
- {
- memcpy(locptr, outbuf + start, rest);
- locptr += rest;
- loccnt += rest;
- }
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
- return (0); /* 0: no error */
- }
-
- /***************************/
- /* Function WriteBuffer() */
- /***************************/
-
- static int WriteBuffer(buf, len)/* return 0 if successful, 1 if not */
- unsigned char *buf;
- int len;
- {
- int status;
-
- status = sys$wait(outrab);
- #ifdef DEBUG
- if (ERR(status))
- {
- message("[ WriteBuffer: sys$wait failed ]\n", status);
- message("", outrab->rab$l_stv);
- }
- #endif
- outrab->rab$w_rsz = len;
- outrab->rab$l_rbf = buf;
-
- if (ERR(status = sys$write(outrab)))
- {
- message("[ WriteBuffer: sys$write failed ]\n", status);
- message("", outrab->rab$l_stv);
- return 50;
- }
- return (0);
- }
-
- /***************************/
- /* Function WriteRecord() */
- /***************************/
-
- static int WriteRecord(rec, len)/* return 0 if successful, 1 if not */
- unsigned char *rec;
- int len;
- {
- int status;
-
- sys$wait(outrab);
- #ifdef DEBUG
- if (ERR(status))
- {
- message("[ WriteRecord: sys$wait faled ]\n", status);
- message("", outrab->rab$l_stv);
- }
- #endif
- outrab->rab$w_rsz = len;
- outrab->rab$l_rbf = rec;
-
- if (ERR(status = sys$put(outrab)))
- {
- message("[ WriteRecord: sys$put failed ]\n", status);
- message("", outrab->rab$l_stv);
- return 50;
- }
- return (0);
- }
-
- /********************************/
- /* Function CloseOutputFile() */
- /********************************/
-
- int CloseOutputFile()
- {
- int status;
-
- if (text_file) _flush_records(1);
- else
- _flush_blocks(1);
- /* Link XABRDT,XABDAT and optionaly XABPRO */
- if (xabrdt != 0L)
- {
- xabrdt->xab$l_nxt = 0L;
- outfab->fab$l_xab = xabrdt;
- }
- else
- {
- rdt.xab$l_nxt = 0L;
- outfab->fab$l_xab = &rdt;
- }
- if (xabdat != 0L)
- {
- xabdat->xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = xabdat;
- }
- if (secinf && xabpro != 0L)
- {
- xabpro->xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = xabpro;
- }
-
- sys$wait(outrab);
-
- status = sys$close(outfab);
- #ifdef DEBUG
- if (ERR(status))
- {
- message("\r[ Warning: cannot set owner/protection/time attributes ]\n", status);
- message("", outfab->fab$l_stv);
- }
- #endif
- free_up();
- }
-
- #ifdef DEBUG
- dump_rms_block(p)
- unsigned char *p;
- {
- unsigned char bid, len;
- int err;
- char *type;
- char buf[132];
- int i;
-
- err = 0;
- bid = p[0];
- len = p[1];
- switch (bid)
- {
- case FAB$C_BID:
- type = "FAB";
- break;
- case XAB$C_ALL:
- type = "xabALL";
- break;
- case XAB$C_KEY:
- type = "xabKEY";
- break;
- case XAB$C_DAT:
- type = "xabDAT";
- break;
- case XAB$C_RDT:
- type = "xabRDT";
- break;
- case XAB$C_FHC:
- type = "xabFHC";
- break;
- case XAB$C_PRO:
- type = "xabPRO";
- break;
- default:
- type = "Unknown";
- err = 1;
- break;
- }
- printf("Block @%08X of type %s (%d).", p, type, bid);
- if (err)
- {
- printf("\n");
- return;
- }
- printf(" Size = %d\n", len);
- printf(" Offset - Hex - Dec\n");
- for (i = 0; i < len; i += 8)
- {
- int j;
-
- printf("%3d - ", i);
- for (j = 0; j < 8; j++)
- if (i + j < len)
- printf("%02X ", p[i + j]);
- else
- printf(" ");
- printf(" - ");
- for (j = 0; j < 8; j++)
- if (i + j < len)
- printf("%03d ", p[i + j]);
- else
- printf(" ");
- printf("\n");
- }
- }
-
- #endif /* DEBUG */
-
- static void message(string, status)
- int status;
- char *string;
- {
- char msgbuf[256];
-
- $DESCRIPTOR(msgd, msgbuf);
- int msglen = 0;
-
- if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
- fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
- else
- {
- msgbuf[msglen] = 0;
- fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
- }
- }
-
-
- #endif /* !ZIPINFO */
- #endif /* VMS */
-